﻿using System;
using System.Drawing;

namespace ExtraControlLibrary
{
    public abstract partial class BasePlot : PartitionedBlankGraph
    {
        protected BasePlot()
        {
            InitializeComponent();
        }

        protected abstract int NumSeries();
        protected abstract SeriesInfo GetSeriesInfo(int idx);

        public abstract void RenderToGraphics(Graphics g, int titleFontSize, int labelFontSize);

        #region Nested type: SingleSeriesInfo

        /// <summary>
        /// SingleSeriesInfo keeps track of x-max, x-min, y-max, y-min, 
        /// as well as the x and y bounds used in the graph.
        /// </summary>
        protected class SeriesInfo
        {
            public struct AxisInfo
            {
                public double Units; // "nice" units
                public double Min, Max; // min and max of data
                public double EdgeMin, EdgeMax; // min and max for edge of graph
                public double LabelMin, LabelMax; // min and max values to be labeled

                public void Register(double value)
                {
                    if (value > Max)
                        Max = value;
                    if (value < Min)
                        Min = value;
                }

                public void ComputeRecommendedUnits()
                {
                    // then y-axis
                    Units = GetNiceUnitForRange(Min, Max, 1.0, false);
                    EdgeMin = Math.Floor(Min / Units) * Units;
                    EdgeMax = Math.Ceiling(Max / Units) * Units;
                    LabelMin = EdgeMin;
                    LabelMax = EdgeMax;
                }
            } ;

            public AxisInfo xinfo;
            public AxisInfo yinfo;

            public SeriesInfo()
            {
                xinfo.Min = double.MaxValue;
                xinfo.Max = double.MinValue;
                yinfo.Min = double.MaxValue;
                yinfo.Max = double.MinValue;
            }

            public void Register(double xvalue, double yvalue)
            {
                xinfo.Register(xvalue);
                yinfo.Register(yvalue);
            }

            public void ComputeUnits()
            {
                xinfo.ComputeRecommendedUnits();
                yinfo.ComputeRecommendedUnits();
            }
        }

        #endregion
    }
}